package erfgame.core.world.terrain.color;


import erfgame.core.util.ColorUtils;
import erfgame.core.world.World;
import erfgame.core.world.terrain.GridSettings;
import erfgame.core.world.terrain.TerrainColorSource;
import erfgame.core.world.terrain.rotated.TransformedBlock;

public class GridTerrainColorSourceProxy implements TerrainColorSource {

	public static final void overlayGrid( 
			TransformedBlock<int[]> colors, 
			int depth, 
			int gridColor, 
			int gridDiagonalMask, 
			GridSettings gridSettings
	) {
		int width = colors.getWidth();
		int height = colors.getHeight();
		int gridMult = gridSettings.opacity;
		int lineWidth = gridSettings.lineWidth;
		int colorMult = (GridSettings.MAX_OPACITY - gridMult) * (lineWidth+1);
		if( lineWidth >= 0 ) {
			for( int x=width; x>0; ) {
				x--;
				for( int y=height; y>0; ) {
					y--;
					int[] colorsxy = colors.getPart(x, y);
					for( int z=depth; z>0; ) {
						z--;
						int c = colorsxy[z];
						int xminusydiff = ((Math.abs(x-y)+lineWidth)&gridDiagonalMask) - lineWidth;
						int xplusydiff = ((x+y+lineWidth)&gridDiagonalMask) - lineWidth;
						if( ( xminusydiff<lineWidth || xplusydiff<lineWidth) ) {
							int diff = lineWidth - Math.min( Math.abs(xminusydiff), Math.abs(xplusydiff) ) + 1;
							int diffMult = diff * gridMult;
							int result = ColorUtils.averageColors(
									c,
									colorMult,
									gridColor, 
									diffMult
							);
							colorsxy[z] = result;
						}
					}
				}
			}
		}	
	}

	
	private GridSettings gridSettings;
	private TerrainColorSource gridSource;
	private TerrainColorSource terrainSource;
	private World world;
	
	public GridTerrainColorSourceProxy( TerrainColorSource terrainSource, TerrainColorSource gridSource, World world, GridSettings gridSettings ) {
		this.terrainSource = terrainSource;
		this.gridSource = gridSource;
		this.gridSettings = gridSettings;
		this.world = world;
	}
	
	public int getColor(int x, int y, int z, int mult, int div, int dCeiling) {
		int result;
		result = this.terrainSource.getColor( x, y, z, mult, div, dCeiling );
		int gridMask = this.world.getGridDiagonalMask();
		// TODO : have a cut off for dsurface scaling, after which we use the terrain colour
		int max = this.gridSettings.lineWidth;
		if( max >= 0 ) {
			int xminusydiff = ((Math.abs(x-y)+max)&gridMask) - max;
			int xplusydiff = ((x+y+max)&gridMask) - max;
			if( ( xminusydiff<max || xplusydiff<max) ) {
				int diff = max - Math.min( Math.abs(xminusydiff), Math.abs(xplusydiff) );
				result = ColorUtils.averageColors(
						result,
						(max+1) * (GridSettings.MAX_OPACITY - gridSettings.opacity),
						this.gridSource.getColor( x, y, z, mult, div, dCeiling ), 
						(diff+1) * gridSettings.opacity
				);
	//			result = ColorUtils.invert( result );
			}
		}
		return result;
	}

}
